home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume3 / sps / part1 next >
Encoding:
Internet Message Format  |  1986-11-30  |  47.7 KB

  1. From: seismo!mcvax!cernvax!hslrswi!robert (Robert Ward)
  2. Subject: SPS (Show Process Status) Part 1 of 2
  3. Newsgroups: mod.sources
  4. Approved: jpn@panda.UUCP
  5.  
  6. Mod.sources:  Volume 3, Issue 55
  7. Submitted by: seismo!mcvax!cernvax!hslrswi!robert (Robert Ward)
  8.  
  9.  
  10. #! /bin/sh
  11. # This is a shell archive, meaning:
  12. # 1. Remove everything above the #! /bin/sh line.
  13. # 2. Save the resulting text in a file.
  14. # 3. Execute the file with /bin/sh (not csh) to create the files:
  15. #    README2
  16. #    README
  17. #    Makefile.4.1
  18. #    Makefile.4.2
  19. #    Makefile.sun
  20. #    filecount.c
  21. #    findtty.c
  22. #    flagdecode.c
  23. #    flags.h
  24. #    flagsetup.c
  25. #    getcmd.c
  26. #    getupage.c
  27. #    globals1.c
  28. #    globals2.c
  29. #    hashuid.c
  30. #    initialise.c
  31. #    initsymbols.c
  32. #    inittty.c
  33. # This archive created: Mon Dec  2 18:40:56 1985
  34. export PATH; PATH=/bin:$PATH
  35. echo shar: extracting "'README2'" '(3050 characters)'
  36. if test -f 'README2'
  37. then
  38.     echo shar: will not over-write existing file "'README2'"
  39. else
  40. sed 's/^X//' << \SHAR_EOF > 'README2'
  41.         SPS  -  Show Process Status
  42.         ===========================
  43.  
  44. XSPS is a intended to be used as a replacement for the standard ps(1)
  45. program. Its advantages over ps(1) are that it shows more useful
  46. information and that it is faster.
  47.  
  48. XSPS is currently implemented for 4.1 and 4.2bsd Unix on Vaxen and for
  49. XSun's 4.2bsd/Release 2. (I also have a somewhat older implementation
  50. for V7 on a PDP-11 as well as Unisoft Version 1.3 on a MC68000 if you
  51. are interested).
  52.  
  53. XSPS displays wait channels symbolically, rather than as hexadecimal
  54. addresses. If you wish to teach sps about a new sort of device, you
  55. must add an entry in the symbol table (globals2.c) as well as
  56. increasing the size of that table (NWAITSTATE in sps.h).
  57.  
  58. XSPS sorts processes before listing them. The order reflects the
  59. relationship of the processes. A child process is listed underneath its
  60. corresponding parent and is indented to depict the exact relationship.
  61. XSPS also indicates setuid processes.
  62.  
  63. XSPS displays such values as the resident and virtual sizes of system
  64. processes.  It accepts a whole range of options to control the output.
  65. By default, SPS lists information about one's own processes. Other
  66. options instruct it to be verbose (the "v" option), to list all the
  67. command arguments of a process (the "w" option) or to list the
  68. environment strings of that process (the "e" option). Similarly, there
  69. are options to control which processes are to be displayed. The "a"
  70. option tells it to describe all processes and the "b" option tells it
  71. to describe "busy" processes, which is useful if you wish to find out
  72. what is loading your system. There are also options to select the
  73. output according to user, controlling tty or process number.
  74.  
  75. XSPS keeps its information in an information file. By default, this is
  76. /etc/spsinfo. This means that it can avoid having to do an expensive
  77. nlist() operation each time it is run. It must be reinitialised (with
  78. the "i" option) if new users are added to /etc/passwd or if a new
  79. version of /vmunix is installed.
  80.  
  81. To compile SPS, unbundle the four shell archive files.  Check that the
  82. define statements in sps.h are large enough for your system (You may
  83. need to alter MAXTTYS).  Then compile it using the appropriate
  84. Makefile. Initialise it by typing "sps i" (ignore any error messages at
  85. this stage) and then test it out by typing "sps va". That should make
  86. XSPS list verbose information about every process currently active. If
  87. that works, use the appropriate Makefile to install it.
  88.  
  89. XSend all bug reports, fixes, comments and suggestions to Robert Ward at -
  90.  
  91. ******************************************************************************
  92.     Robert Ward,
  93.     Hasler AG, Murtenstrasse 137a, CH-3008 Bern, Switzerland
  94.  
  95. Tel.:        (031) - 65 23 19
  96. Uucp:        ... {seismo,decvax,ukc, ... }!mcvax!cernvax!hslrswi!robert
  97. Bitnet:        hslrswi!robert@cernvax.bitnet
  98. Arpa:        hslrswi!robert%cernvax.bitnet@WISCVM.ARPA
  99. Edunet:        hslrswi!robert%cernvax.bitnet@UCBJADE.Berkeley.EDU
  100. ******************************************************************************
  101. SHAR_EOF
  102. if test 3050 -ne "`wc -c < 'README2'`"
  103. then
  104.     echo shar: error transmitting "'README2'" '(should have been 3050 characters)'
  105. fi
  106. fi # end of overwriting check
  107. echo shar: extracting "'README'" '(1226 characters)'
  108. if test -f 'README'
  109. then
  110.     echo shar: will not over-write existing file "'README'"
  111. else
  112. sed 's/^X//' << \SHAR_EOF > 'README'
  113.         SPS - Show Process Status
  114.         =========================
  115. To compile, install and test, type the following commands (as super-user):
  116.     % make                  # Compile SPS
  117.     % make install          # Install SPS into /bin/sps
  118.     % sps i                 # Initialise SPS
  119.     % sps va                # Run SPS
  120. ********************************************************************************
  121. The files in this directory are for the 4.[12]BSD / VAX-11 version of SPS.
  122. Compiler options are as follows -
  123.     -DCHAOS         if the Chaos network is incorporated into 4.xbsd
  124.     -DTRACE         for testing/debugging purposes
  125.     -DBSD42         compile SPS for 4.2bsd.
  126.             Otherwise, SPS is compiled for 4.1bsd.
  127. ********************************************************************************
  128. If you want to tell SPS about a new type of device, then add a new line to
  129. the symbol table (see globals2.c),after ensuring that there is sufficient
  130. room in the `info' structure. (NWAITSTATE may need to be increased in sps.h).
  131. ********************************************************************************
  132. XSPS understands if the size of internal kernel tables are changed under VMUNIX,
  133. but must be recompiled if major modifications are made to the kernel.
  134. SHAR_EOF
  135. if test 1226 -ne "`wc -c < 'README'`"
  136. then
  137.     echo shar: error transmitting "'README'" '(should have been 1226 characters)'
  138. fi
  139. fi # end of overwriting check
  140. echo shar: extracting "'Makefile.4.1'" '(882 characters)'
  141. if test -f 'Makefile.4.1'
  142. then
  143.     echo shar: will not over-write existing file "'Makefile.4.1'"
  144. else
  145. sed 's/^X//' << \SHAR_EOF > 'Makefile.4.1'
  146. # Makefile for SPS (4.1BSD UNIX Version)
  147.  
  148. PROG    =       sps
  149. OBJS    =       filecount.o findtty.o flagdecode.o flagsetup.o \
  150.         getcmd.o getupage.o globals1.o globals2.o hashuid.o \
  151.         initialise.o initsymbols.o inittty.o main.o mktree.o \
  152.         needed.o openfiles.o percentmem.o prcmd.o prcpu.o \
  153.         prheader.o printall.o printproc.o prsummary.o readstatus.o \
  154.         selectproc.o selecttty.o termwidth.o ttystatus.o waitingfor.o
  155.  
  156. INCS    =       sps.h
  157. LIBS    =       -ltermlib
  158. CFLAGS  =       -I/usr/src/sys -DCHAOS
  159.  
  160. all:            $(PROG)
  161. X.c.o:
  162.         cc $(CFLAGS) -c -O -R $<
  163. globals1.o waitingfor.o:
  164.         cc $(CFLAGS) -c -O $<
  165.  
  166. $(OBJS):        $(INCS)
  167.  
  168. $(PROG):        $(OBJS)
  169.         cc -o $@ $(OBJS) $(LIBS)
  170.  
  171. install:        $(PROG)
  172.         strip $(PROG)
  173.         mv $(PROG) /bin/$(PROG)
  174.         /etc/chown root /bin/$(PROG)
  175.         chmod 4711 /bin/$(PROG)
  176.  
  177. lint:
  178.         lint -x -b $(CFLAGS) *.c
  179. clean:
  180.         rm -f $(OBJS) $(PROG)
  181. SHAR_EOF
  182. if test 882 -ne "`wc -c < 'Makefile.4.1'`"
  183. then
  184.     echo shar: error transmitting "'Makefile.4.1'" '(should have been 882 characters)'
  185. fi
  186. fi # end of overwriting check
  187. echo shar: extracting "'Makefile.4.2'" '(853 characters)'
  188. if test -f 'Makefile.4.2'
  189. then
  190.     echo shar: will not over-write existing file "'Makefile.4.2'"
  191. else
  192. sed 's/^X//' << \SHAR_EOF > 'Makefile.4.2'
  193. # Makefile for SPS (4.2BSD UNIX Version)
  194.  
  195. PROG    =       sps
  196. OBJS    =       filecount.o findtty.o flagdecode.o flagsetup.o \
  197.         getcmd.o getupage.o globals1.o globals2.o hashuid.o \
  198.         initialise.o initsymbols.o inittty.o main.o mktree.o \
  199.         needed.o openfiles.o percentmem.o prcmd.o prcpu.o \
  200.         prheader.o printall.o printproc.o prsummary.o readstatus.o \
  201.         selectproc.o selecttty.o termwidth.o ttystatus.o waitingfor.o
  202. INCS    =       sps.h
  203. CC      =       cc
  204. CFLAGS  =       -DBSD42 -I/sys
  205. LIBS    =       -ltermlib
  206.  
  207. all:            $(PROG)
  208. X.c.o:
  209.         $(CC) $(CFLAGS) -c -O -R $<
  210.     
  211. globals1.o waitingfor.o:
  212.         $(CC) $(CFLAGS) -c -O $<
  213.  
  214. $(OBJS):        $(INCS)
  215.  
  216. $(PROG):        $(OBJS)
  217.         $(CC) -o $@ $(OBJS) $(LIBS)
  218.  
  219. install:        $(PROG)
  220.         strip $(PROG)
  221.         mv $(PROG) /bin/$(PROG)
  222.         /etc/chown root /bin/$(PROG)
  223.  
  224. lint:
  225.         lint -x -b $(CFLAGS) *.c
  226. clean:
  227.         rm -f $(OBJS) $(PROG)
  228. SHAR_EOF
  229. if test 853 -ne "`wc -c < 'Makefile.4.2'`"
  230. then
  231.     echo shar: error transmitting "'Makefile.4.2'" '(should have been 853 characters)'
  232. fi
  233. fi # end of overwriting check
  234. echo shar: extracting "'Makefile.sun'" '(863 characters)'
  235. if test -f 'Makefile.sun'
  236. then
  237.     echo shar: will not over-write existing file "'Makefile.sun'"
  238. else
  239. sed 's/^X//' << \SHAR_EOF > 'Makefile.sun'
  240. # Makefile for SPS (Sun 4.2BSD UNIX Version)
  241.  
  242. PROG    =       sps
  243. OBJS    =       filecount.o findtty.o flagdecode.o flagsetup.o \
  244.         getcmd.o getupage.o globals1.o globals2.o hashuid.o \
  245.         initialise.o initsymbols.o inittty.o main.o mktree.o \
  246.         needed.o openfiles.o percentmem.o prcmd.o prcpu.o \
  247.         prheader.o printall.o printproc.o prsummary.o readstatus.o \
  248.         selectproc.o selecttty.o termwidth.o ttystatus.o waitingfor.o
  249. INCS    =       sps.h
  250. CC      =       cc
  251. CFLAGS  =       -DSUN -DBSD42 -I/sys
  252. LIBS    =       -ltermlib
  253.  
  254. all:            $(PROG)
  255. X.c.o:
  256.         $(CC) $(CFLAGS) -c -O -R $<
  257.     
  258. globals1.o waitingfor.o:
  259.         $(CC) $(CFLAGS) -c -O $<
  260.  
  261. $(OBJS):        $(INCS)
  262.  
  263. $(PROG):        $(OBJS)
  264.         $(CC) -o $@ $(OBJS) $(LIBS)
  265.  
  266. install:        $(PROG)
  267.         strip $(PROG)
  268.         mv $(PROG) /bin/$(PROG)
  269.         /etc/chown root /bin/$(PROG)
  270.  
  271. lint:
  272.         lint -x -b $(CFLAGS) *.c
  273. clean:
  274.         rm -f $(OBJS) $(PROG)
  275. SHAR_EOF
  276. if test 863 -ne "`wc -c < 'Makefile.sun'`"
  277. then
  278.     echo shar: error transmitting "'Makefile.sun'" '(should have been 863 characters)'
  279. fi
  280. fi # end of overwriting check
  281. echo shar: extracting "'filecount.c'" '(351 characters)'
  282. if test -f 'filecount.c'
  283. then
  284.     echo shar: will not over-write existing file "'filecount.c'"
  285. else
  286. sed 's/^X//' << \SHAR_EOF > 'filecount.c'
  287. # include       "sps.h"
  288.  
  289. /* FILECOUNT - Counts the # open files for the current process */
  290. filecount ()
  291. {
  292.     register int            i ;
  293.     register struct file    **f ;
  294.     register int            count ;
  295.     extern union userstate  User ;
  296.  
  297.     count = 0 ;
  298.     for ( i = 0, f = User.u_us.u_ofile ; i < NOFILE ; i++ )
  299.         if ( *f++ )
  300.             count++ ;
  301.     return ( count ) ;
  302. }
  303. SHAR_EOF
  304. if test 351 -ne "`wc -c < 'filecount.c'`"
  305. then
  306.     echo shar: error transmitting "'filecount.c'" '(should have been 351 characters)'
  307. fi
  308. fi # end of overwriting check
  309. echo shar: extracting "'findtty.c'" '(505 characters)'
  310. if test -f 'findtty.c'
  311. then
  312.     echo shar: will not over-write existing file "'findtty.c'"
  313. else
  314. sed 's/^X//' << \SHAR_EOF > 'findtty.c'
  315. # include       "sps.h"
  316. # include       <h/tty.h>
  317.  
  318. /* FINDTTY - Attempts to determine to which tty a process is connected */
  319. struct ttyline  *findtty ( p )
  320.  
  321. register struct process         *p ;
  322.  
  323. {
  324.     register struct ttyline *lp ;
  325.     extern struct info      Info ;
  326.     extern struct ttyline   Notty ;
  327.     extern union userstate  User ;
  328.  
  329.     if ( !p->pr_p.p_pgrp )
  330.         return ( &Notty ) ;
  331.     for ( lp = Info.i_ttyline ; lp->l_name[0] ; lp++ )
  332.         if ( lp->l_dev == User.u_us.u_ttyd )
  333.             return ( lp ) ;
  334.     return ( &Notty ) ;
  335. }
  336. SHAR_EOF
  337. if test 505 -ne "`wc -c < 'findtty.c'`"
  338. then
  339.     echo shar: error transmitting "'findtty.c'" '(should have been 505 characters)'
  340. fi
  341. fi # end of overwriting check
  342. echo shar: extracting "'flagdecode.c'" '(5436 characters)'
  343. if test -f 'flagdecode.c'
  344. then
  345.     echo shar: will not over-write existing file "'flagdecode.c'"
  346. else
  347. sed 's/^X//' << \SHAR_EOF > 'flagdecode.c'
  348. # include       "sps.h"
  349. # include       "flags.h"
  350.  
  351. /* FLAGDECODE - Looks at the argument list and sets various internal switches */
  352. flagdecode ( argc, argv )
  353.  
  354. register int                    argc ;
  355. register char                   **argv ;
  356.  
  357. {
  358.     register char           *chp ;
  359.     union flaglist          *plist ;
  360.     union flaglist          *tlist ;
  361.     union flaglist          *ulist ;
  362.     static char             usage[] =
  363.     "sps - Unknown option %s\nUsage - sps [ -defgijkoqrsvwyABFNPSTUWZ ][ process|tty|user ] ...\n";
  364.     union flaglist          *getflgsp() ;
  365.     extern struct flags     Flg ;
  366.  
  367.     plist = tlist = ulist = (union flaglist*)0 ;
  368.     for ( argv++ ; --argc ; argv++ )
  369.     {
  370.         chp = *argv ;
  371.         while ( *chp )
  372.             switch ( *chp++ )
  373.             {
  374.                 case '-' :
  375.                     /* Separation character */
  376.                     continue ;
  377.                 case 'd' :
  378.                 case 'D' :
  379.                     /* List disc orientated information */
  380.                     Flg.flg_d = 1 ;
  381.                     Flg.flg_v = 0 ;
  382.                     continue ;
  383.                 case 'e' :
  384.                 case 'E' :
  385.                     /* List environment strings */
  386.                     Flg.flg_e = 1 ;
  387.                     continue ;
  388.                 case 'f' :
  389.                     /* List the father's process id */
  390.                     Flg.flg_f = 1 ;
  391.                     continue ;
  392.                 case 'g' :
  393.                 case 'G' :
  394.                     /* List the process group id */
  395.                     Flg.flg_g = 1 ;
  396.                     continue ;
  397.                 case 'i' :
  398.                 case 'I' :
  399.                     /* Initialise (super-user only) */
  400.                     Flg.flg_i = 1 ;
  401.                     continue ;
  402.                 case 'j' :
  403.                 case 'J' :
  404.                     /* The next argument specifies the
  405.                        name of the information file */
  406.                     if ( argc <= 1 )
  407.                         prexit(
  408.           "sps - Name of an information file expected after `-j' flag\n" ) ;
  409.                     argc-- ;
  410.                     Flg.flg_j = *++argv ;
  411.                     continue ;
  412.                 case 'k' :
  413.                 case 'K' :
  414.                     /* Use a disc file such as /vmcore
  415.                        rather than /dev/{k}mem for
  416.                        accessing kernel data. The next
  417.                        argument specifies the file name. */
  418.                     if ( argc <= 1 )
  419.                         prexit(
  420.            "sps - Name of a memory dump file expected after `-k' flag\n" ) ;
  421.                     argc-- ;
  422.                     Flg.flg_k = *++argv ;
  423.                     Flg.flg_o = 1 ;
  424.                     continue ;
  425.                 case 'l' :
  426.                 case 'v' :
  427.                 case 'L' :
  428.                 case 'V' :
  429.                     /* Verbose output */
  430.                     Flg.flg_d = 0 ;
  431.                     Flg.flg_v = 1 ;
  432.                     continue ;
  433.                 case 'o' :
  434.                 case 'O' :
  435.                     /* Avoid looking at the swap device */
  436.                     Flg.flg_o = 1 ;
  437.                     continue ;
  438.                 case 'q' :
  439.                 case 'Q' :
  440.                     /* Show only the user time, not the
  441.                        user + system times together. */
  442.                     Flg.flg_q = 1 ;
  443.                     continue ;
  444.                 case 'r' :
  445.                 case 'R' :
  446.                     /* Repeat output every n seconds.
  447.                        The next argument specifies n which
  448.                        defaults to 5 if omitted. */
  449.                     Flg.flg_r = 1 ;
  450.                     if ( argc > 1 )
  451.                     {
  452.                         if ( **++argv >= '0'
  453.                         && **argv <= '9' )
  454.                         {
  455.                             argc-- ;
  456.                             Flg.flg_rdelay
  457.                                    = atoi( *argv ) ;
  458.                             continue ;
  459.                         }
  460.                         argv-- ;
  461.                     }
  462.                     Flg.flg_rdelay = 0 ;
  463.                     continue ;
  464.                 case 's' :
  465.                     /* Next argument specifies a symbol
  466.                        file rather than the default
  467.                        /vmunix. */
  468.                     if ( argc <= 1 )
  469.                         prexit(
  470.             "sps - Name of a symbol file expected after `-s' flag\n" ) ;
  471.                     argc-- ;
  472.                     Flg.flg_s = *++argv ;
  473.                     continue ;
  474.                 case 'w' :
  475.                     /* Wide output, exceeding 79 columns */
  476.                     Flg.flg_w = 1 ;
  477.                     continue ;
  478.                 case 'y' :
  479.                 case 'Y' :
  480.                     /* List current tty information */
  481.                     Flg.flg_y = 1 ;
  482.                     continue ;
  483.                 case 'a' :
  484.                 case 'A' :
  485.                     /* List all processes */
  486.                     Flg.flg_AZ = 1 ;
  487.                     Flg.flg_A = 1 ;
  488.                     continue ;
  489.                 case 'b' :
  490.                 case 'B' :
  491.                     /* List only busy processes */
  492.                     Flg.flg_AZ = 1 ;
  493.                     Flg.flg_B = 1 ;
  494.                     continue ;
  495.                 case 'F' :
  496.                     /* List only foreground processes */
  497.                     Flg.flg_AZ = 1 ;
  498.                     Flg.flg_F = 1 ;
  499.                     continue ;
  500.                 case 'n' :
  501.                 case 'N' :
  502.                     /* No processes, just the summary line*/
  503.                     Flg.flg_AZ = 1 ;
  504.                     Flg.flg_N = 1 ;
  505.                     continue ;
  506.                 case 'p' :
  507.                 case 'P' :
  508.                     /* List only the given process ids */
  509.                     Flg.flg_AZ = 1 ;
  510.                     Flg.flg_P = 1 ;
  511.                     if ( !plist )
  512.                        plist=Flg.flg_Plist=getflgsp( argc );
  513.                     while ( argc > 1 )
  514.                     {
  515.                         if ( **++argv == '-' )
  516.                         {
  517.                             --argv ;
  518.                             break ;
  519.                         }
  520.                         --argc ;
  521.                         plist->f_chp = *argv ;
  522.                         (++plist)->f_chp = (char*)0 ;
  523.                     }
  524.                     continue ;
  525.                 case 'S' :
  526.                     /* List only stopped processes */
  527.                     Flg.flg_AZ = 1 ;
  528.                     Flg.flg_S = 1 ;
  529.                     continue ;
  530.                 case 't' :
  531.                 case 'T' :
  532.                     /* List only processes attached to the
  533.                        specified terminals */
  534.                     Flg.flg_AZ = 1 ;
  535.                     Flg.flg_T = 1 ;
  536.                     if ( !tlist )
  537.                        tlist=Flg.flg_Tlist=getflgsp( argc );
  538.                     while ( argc > 1 )
  539.                     {
  540.                         if ( **++argv == '-' )
  541.                         {
  542.                             --argv ;
  543.                             break ;
  544.                         }
  545.                         --argc ;
  546.                         tlist->f_chp = *argv ;
  547.                         (++tlist)->f_chp = (char*)0 ;
  548.                     }
  549.                     continue ;
  550.                 case 'u' :
  551.                 case 'U' :
  552.                     /* List only processes belonging to the
  553.                        specified users */
  554.                     Flg.flg_AZ = 1 ;
  555.                     Flg.flg_U = 1 ;
  556.                     if ( !ulist )
  557.                        ulist=Flg.flg_Ulist=getflgsp( argc );
  558.                     while ( argc > 1 )
  559.                     {
  560.                         if ( **++argv == '-' )
  561.                         {
  562.                             --argv ;
  563.                             break ;
  564.                         }
  565.                         --argc ;
  566.                         ulist->f_chp = *argv ;
  567.                         (++ulist)->f_chp = (char*)0 ;
  568.                     }
  569.                     continue ;
  570.                 case 'W' :
  571.                     /* List only waiting processes */
  572.                     Flg.flg_AZ = 1 ;
  573.                     Flg.flg_W = 1 ;
  574.                     continue ;
  575.                 case 'z' :
  576.                 case 'Z' :
  577.                     /* List only zombie processes */
  578.                     Flg.flg_AZ = 1 ;
  579.                     Flg.flg_Z = 1 ;
  580.                     continue ;
  581.                 default :
  582.                     prexit( usage, *argv ) ;
  583.                     /* NOTREACHED */
  584.             }
  585.     }
  586. }
  587. SHAR_EOF
  588. if test 5436 -ne "`wc -c < 'flagdecode.c'`"
  589. then
  590.     echo shar: error transmitting "'flagdecode.c'" '(should have been 5436 characters)'
  591. fi
  592. fi # end of overwriting check
  593. echo shar: extracting "'flags.h'" '(2488 characters)'
  594. if test -f 'flags.h'
  595. then
  596.     echo shar: will not over-write existing file "'flags.h'"
  597. else
  598. sed 's/^X//' << \SHAR_EOF > 'flags.h'
  599. /* Structure holding information specified in the option list ... */
  600. union flaglist
  601. {
  602.     char                    *f_chp ;        /* Option specified as string */
  603.     int                     f_uid ;         /* Numerical user id */
  604.     int                     f_pid ;         /* Numerical process id */
  605.     struct ttyline          *f_ttyline ;    /* Specified tty */
  606. } ;
  607.  
  608. /* Structure holding global information specifed by arg list options ... */
  609. struct flags
  610. {
  611.     int                     flg_d:1 ;       /* disc orientated output */
  612.     int                     flg_e:1 ;       /* print environment string */
  613.     int                     flg_f:1 ;       /* print process father # */
  614.     int                     flg_g:1 ;       /* print process group # */
  615.     int                     flg_i:1 ;       /* initialise sps */
  616.     char                    *flg_j ;        /* Use this as the info file */
  617.     char                    *flg_k ;        /* Use this as the {k}mem file*/
  618.     int                     flg_o:1 ;       /* avoid the swap device */
  619.     int                     flg_q:1 ;       /* show user time only */
  620.     int                     flg_r:1 ;       /* repeat output */
  621.     unsigned                flg_rdelay ;    /* ... with this much delay */
  622.     char                    *flg_s ;        /* Use this as the symbol file*/
  623.     int                     flg_v:1 ;       /* print verbose listing */
  624.     int                     flg_w:1 ;       /* print wide output */
  625.     int                     flg_y:1 ;       /* print tty information */
  626.     int                     flg_A:1 ;       /* print all processes */
  627.     int                     flg_B:1 ;       /* print busy processes */
  628.     int                     flg_F:1 ;       /* print foreground processes */
  629.     int                     flg_N:1 ;       /* print no processes */
  630.     int                     flg_P:1 ;       /* print specified process #'s*/
  631.     int                     flg_S:1 ;       /* print stopped processes */
  632.     int                     flg_T:1 ;       /* print procs for given ttys */
  633.     int                     flg_U:1 ;       /* print procs for given users*/
  634.     int                     flg_W:1 ;       /* print waiting processes */
  635.     int                     flg_Z:1 ;       /* print zombie processes */
  636.     int                     flg_AZ:1 ;      /* One of A to Z was specified*/
  637.     union flaglist          *flg_Plist ;    /* List of specified processes*/
  638.     union flaglist          *flg_Tlist ;    /* List of specified ttys */
  639.     union flaglist          *flg_Ulist ;    /* List of specified users */
  640. } ;
  641. SHAR_EOF
  642. if test 2488 -ne "`wc -c < 'flags.h'`"
  643. then
  644.     echo shar: error transmitting "'flags.h'" '(should have been 2488 characters)'
  645. fi
  646. fi # end of overwriting check
  647. echo shar: extracting "'flagsetup.c'" '(2182 characters)'
  648. if test -f 'flagsetup.c'
  649. then
  650.     echo shar: will not over-write existing file "'flagsetup.c'"
  651. else
  652. sed 's/^X//' << \SHAR_EOF > 'flagsetup.c'
  653. # include       "sps.h"
  654. # include       "flags.h"
  655. # include       <h/tty.h>
  656.  
  657. /*
  658. ** FLAGSETUP - Replaces any users or processes specified by flagdecode()
  659. ** with numerical equivalents. The lists are terminated by negative values.
  660. ** or null pointers. Ttystatus() must have been previously called to
  661. ** initialise the Info structure with chaos tty values.
  662. */
  663. flagsetup ()
  664. {
  665.     register union flaglist *fp ;
  666.     register char           *chp ;
  667.     register int            i ;
  668.     register struct ttyline *lp ;
  669.     int                     found ;
  670.     extern struct flags     Flg ;
  671.     extern struct info      Info ;
  672.  
  673.     /* Look for specified users */
  674.     if ( Flg.flg_U )                
  675.     {
  676.         if ( !Flg.flg_Ulist->f_chp )
  677.             prexit( "sps - User name was expected after -u flag\n");
  678.         for ( fp = Flg.flg_Ulist ; chp = fp->f_chp ; fp++ )
  679.         {
  680.             found = 0 ;
  681.             for ( i = 0 ; i < MAXUSERID ; i++ )
  682.                 if ( !strncmp( chp, Info.i_hnames[i].h_uname,
  683.                     UNAMELEN ) )
  684.                 {
  685.                     fp->f_uid = Info.i_hnames[i].h_uid ;
  686.                     found = 1 ;
  687.                     break ;
  688.                 }
  689.             if ( !found )
  690.                 prexit( "sps - Unknown user: %s\n", chp ) ;
  691.         }
  692.         fp->f_uid = -1 ;
  693.     }
  694.     /* Look for specified process ids */
  695.     if ( Flg.flg_P )                
  696.     {
  697.         if ( !Flg.flg_Plist->f_chp )
  698.             prexit(
  699.                  "sps - Process id was expected after -p flag\n" ) ;
  700.         for ( fp = Flg.flg_Plist ; chp = fp->f_chp ; fp++ )
  701.         {
  702.             if ( chp[0] < '0' || chp[0] > '9' )
  703.                 prexit( "sps - Bad process id: %s\n", chp ) ;
  704.             fp->f_pid = atoi( chp ) ;
  705.         }
  706.         fp->f_pid = -1 ;
  707.     }
  708.     /* Look for specified ttys */
  709.     if ( !Flg.flg_T )               
  710.         return ;
  711.     if ( !Flg.flg_Tlist->f_chp )
  712.         prexit( "sps - Tty name was expected after -t flag\n" ) ;
  713.     for ( fp = Flg.flg_Tlist ; chp = fp->f_chp ; fp++ )
  714.     {       /* Under VMUNIX, all ttys have two character names.
  715.            Thus, a flag of the form `t 8' should be expanded to
  716.            become `t 08'. */
  717.         if ( !chp[1] )
  718.             chp[1] = chp[0], chp[0] = '0' ;
  719.         found = 0 ;
  720.         for ( lp = Info.i_ttyline ; lp->l_name[0] ; lp++ )
  721.             if ( !strncmp( chp, lp->l_name, 2 ) )
  722.             {
  723.                 fp->f_ttyline = lp ;
  724.                 found = 1 ;
  725.                 break ;
  726.             }
  727.         if ( !found )
  728.             prexit( "sps - Unknown tty name: %.2s\n", chp ) ;
  729.     }
  730.     fp->f_ttyline = (struct ttyline*)0 ;
  731. }
  732. SHAR_EOF
  733. if test 2182 -ne "`wc -c < 'flagsetup.c'`"
  734. then
  735.     echo shar: error transmitting "'flagsetup.c'" '(should have been 2182 characters)'
  736. fi
  737. fi # end of overwriting check
  738. echo shar: extracting "'getcmd.c'" '(4815 characters)'
  739. if test -f 'getcmd.c'
  740. then
  741.     echo shar: will not over-write existing file "'getcmd.c'"
  742. else
  743. sed 's/^X//' << \SHAR_EOF > 'getcmd.c'
  744. # include       "sps.h"
  745. # include       "flags.h"
  746. # include       <h/vm.h>
  747. # ifdef BSD42
  748. # include    <machine/pte.h>
  749. # else
  750. # include       <h/pte.h>
  751. # endif
  752.  
  753. /*
  754. ** GETCMD - Returns a character string read from a process' upage.
  755. ** This character string should represent the arguments to the current process.
  756. */
  757. char    *getcmd ( p )
  758.  
  759. register struct process         *p ;
  760.  
  761. {
  762.     register int            *ip ;
  763.     register char           *cp ;
  764.     register char           *cp0 ;
  765.     unsigned                nbad ;
  766.     struct dblock           db ;
  767.     struct pte              ptetbl[ UPAGES + CLSIZE ] ;
  768.     union
  769.     {
  770.         char            a_argc[ CLSIZE * NBPG ] ;
  771.         int             a_argi[ CLSIZE * NBPG / sizeof( int ) ] ;
  772.     } argbuf ;
  773.     extern struct flags     Flg ;
  774.     extern union userstate  User ;
  775.     extern int              Flmem, Flswap ;
  776.     char                    *strcat(), *strncpy(), *strsave() ;
  777.  
  778.     p->pr_csaved = 0 ;
  779.     p->pr_upag = 0 ;
  780.     if ( p->pr_p.p_stat == SZOMB )
  781.         return ( "** Exit **" ) ;
  782.     if ( !(p->pr_p.p_flag & SLOAD) && Flg.flg_o )
  783.         return ( "** Swapped out **" ) ;
  784.     /* Find the process' upage */
  785.     if ( !getupage( p, ptetbl ) )           
  786.         return ( "** No upage **" ) ;
  787.     /* Is this a system process ? */
  788.     if ( p->pr_p.p_flag & SSYS )            
  789.         switch ( p->pr_p.p_pid )
  790.         {
  791.             case 0 :
  792.                 p->pr_upag = 1 ;
  793.                 return ( "Unix Swapper" ) ;
  794.             case 2 :
  795.                 p->pr_upag = 1 ;
  796.                 return ( "Unix Pager" ) ;
  797.             default :
  798.                 break ;
  799.         }
  800.     /* Look at the top of the upage to locate the command arguments.
  801.        The page is loaded if the process itself is loaded and the pte
  802.        contains is marked as valid. */
  803.     if ( (p->pr_p.p_flag & SLOAD)
  804.     && !ptetbl[0].pg_fod && ptetbl[0].pg_pfnum )
  805.     {       /* If the page is loaded, read the arguments from
  806.            physical memory. */
  807.         memseek( Flmem, (long)ctob( ptetbl[0].pg_pfnum ) ) ;
  808.         if ( read( Flmem, argbuf.a_argc, CLSIZE*NBPG ) != CLSIZE*NBPG )
  809.             return ( "** Memory read error **" ) ;
  810.     }
  811.     else                            
  812.     {       /* Otherwise the page is on the swap device */
  813.         vstodb( 0, ctod( CLSIZE ), &User.u_us.u_smap, &db, 1 ) ;
  814. # ifdef BSD42
  815.         swseek( (long)dtob( db.db_base ) ) ;
  816. # else
  817.         swseek( (long)ctob( db.db_base ) ) ;
  818. # endif
  819.         if ( Flg.flg_o )
  820.             return ( "** Swapped page **" ) ;
  821.         if ( read( Flswap, argbuf.a_argc, CLSIZE*NBPG ) != CLSIZE*NBPG )
  822.             return ( "** Swap device read error **" ) ;
  823.     }
  824.     /* Look down until the end of command arguments is found. */
  825.     p->pr_upag = 1 ;
  826.     p->pr_csaved = 1 ;
  827.     ip = &argbuf.a_argi[ CLSIZE*NBPG / sizeof( int ) ] ;
  828.     ip -= 2 ;
  829.     while ( *--ip )
  830.         if ( ip == &argbuf.a_argi[0] )
  831.             goto getsysargs ;
  832.     /* Process the command arguments, looking for nulls and unprintable
  833.        characters. */
  834.     cp0 = (char*)(ip + 1) ;
  835.     if ( !*cp0 )                    
  836.         cp0++ ;                 
  837.     if ( *cp0 )
  838.     {
  839.         nbad = 0 ;                      
  840.         for ( cp = cp0 ; cp < &argbuf.a_argc[ CLSIZE*NBPG ] ; cp++ )
  841.         {
  842.             *cp &= 0177 ;
  843.             if ( !*cp )             
  844.             {       /* Replace nulls with spaces */
  845.                 *cp = ' ' ;
  846.                 continue ;
  847.             }
  848.             if ( *cp < ' ' || *cp == 0177 )
  849.             {       /* Replace control characters with ?'s */
  850.                 if ( ++nbad > 5 )
  851.                 {
  852.                     *cp++ = ' ' ;
  853.                     break ;
  854.                 }
  855.                 *cp = '?' ;
  856.                 continue ;
  857.             }
  858.             if ( !Flg.flg_e && *cp == '=' )
  859.             {       /* Break on an `=' if we are not interested
  860.                    in the environment strings. */
  861.                 *cp = '\0' ;
  862.                 while ( cp > cp0 && *--cp != ' ' )
  863.                     *cp = '\0' ;
  864.                 break ;
  865.             }
  866.         }
  867.         while ( *--cp == ' ' )
  868.             *cp = '\0' ;
  869.         return ( strsave( cp0 ) ) ;
  870.     }
  871. getsysargs :
  872.     /* If the command arguments cannot be accessed from the user's memory
  873.        space, get the command name from the system's idea of what the
  874.        name should be. */
  875.     argbuf.a_argc[0] = '(' ;
  876.     (void)strncpy( &argbuf.a_argc[1], User.u_us.u_comm,
  877.         sizeof( User.u_us.u_comm ) ) ;
  878.     (void)strcat( &argbuf.a_argc[0], ")" ) ;
  879.     return ( strsave( argbuf.a_argc ) ) ;
  880. }
  881.  
  882. /*
  883. ** VSTODB - Given a base/size pair in virtual swap area,
  884. ** return a physical base/size pair which is the
  885. ** (largest) initial, physically contiguous block.
  886. /* This code is stolen from the kernel file /sys/sys/vm_drum.c.
  887. */
  888. vstodb ( vsbase, vssize, dmp, dbp, rev )
  889.  
  890. register int                    vsbase ;
  891. register int                    vssize;
  892. struct dmap                     *dmp ;
  893. register struct dblock          *dbp ;
  894. int                             rev ;
  895.  
  896. {
  897.     register int            blk ;
  898.     register swblk_t        *ip ;
  899. # ifdef BSD42
  900.     extern struct info      Info ;
  901. # endif
  902.  
  903. # ifdef BSD42
  904.     blk = Info.i_dmmin ;
  905. # else
  906.     blk = DMMIN ;
  907. # endif
  908.     ip = dmp->dm_map ;
  909.     while ( vsbase >= blk )
  910.     {
  911.         vsbase -= blk ;
  912. # ifdef BSD42
  913.         if ( blk < Info.i_dmmax )
  914. # else
  915.         if ( blk < DMMAX )
  916. # endif
  917.             blk *= 2 ;
  918.         ip++ ;
  919.     }
  920.     dbp->db_size = vssize < blk - vsbase ? vssize : blk - vsbase ;
  921.     dbp->db_base = *ip + (rev ? blk - (vsbase + dbp->db_size) : vsbase);
  922. }
  923. SHAR_EOF
  924. if test 4815 -ne "`wc -c < 'getcmd.c'`"
  925. then
  926.     echo shar: error transmitting "'getcmd.c'" '(should have been 4815 characters)'
  927. fi
  928. fi # end of overwriting check
  929. echo shar: extracting "'getupage.c'" '(2971 characters)'
  930. if test -f 'getupage.c'
  931. then
  932.     echo shar: will not over-write existing file "'getupage.c'"
  933. else
  934. sed 's/^X//' << \SHAR_EOF > 'getupage.c'
  935. # include       "sps.h"
  936. # include       <h/vm.h>
  937. # ifdef BSD42
  938. # include    <machine/pte.h>
  939. # else
  940. # include       <h/pte.h>
  941. # endif
  942. # include       <stdio.h>
  943.  
  944. /*
  945. ** GETUPAGE - Reads the upage for the specified process as well as sufficient
  946. ** page tables entries for reading the command arguments. The pte's are read
  947. ** into the argument `ptetbl'. The upage is read into the external variable
  948. ** `User'. This procedure returns 1 if the upage was successfully read.
  949. */
  950.  
  951. # define        usrpt           (Info.i_usrpt)
  952.  
  953. getupage ( p, ptetbl )
  954.  
  955. register struct process         *p ;
  956. register struct pte             *ptetbl ;
  957.  
  958. {
  959.     register int            i ;
  960.     register int            ncl ;
  961.     struct pte              pte ;
  962.     extern struct info      Info ;
  963.     extern union userstate  User ;
  964.     extern int              Flmem, Flkmem, Flswap ;
  965.  
  966.     /* If the process is not loaded, look for the upage on the swap device*/
  967.     if ( !(p->pr_p.p_flag & SLOAD) )
  968.     {                               
  969. # ifdef BSD42
  970.         swseek( (long)dtob( p->pr_p.p_swaddr ) ) ;
  971. # else
  972.         swseek( (long)ctob( p->pr_p.p_swaddr ) ) ;
  973. # endif
  974. # ifdef SUN
  975.         if ( read( Flswap, (char*)&User.u_us, sizeof( union userstate ))
  976.         != sizeof( union userstate ) )
  977. # else
  978.         if ( read( Flswap, (char*)&User.u_us, sizeof( struct user ) )
  979.         != sizeof( struct user ) )
  980. # endif
  981.         {
  982.             fprintf( stderr,
  983.                 "sps - Can't read upage of process %d\n",
  984.                 p->pr_p.p_pid ) ;
  985.             return ( 0 ) ;
  986.         }
  987.         return ( 1 ) ;          
  988.     }                               
  989.     /* The process is loaded. Locate the process pte's by reading
  990.        the pte of their base address from system virtual address space. */
  991.     memseek( Flkmem, (long)&Info.i_usrptmap[ btokmx(p->pr_p.p_p0br)
  992.         + p->pr_p.p_szpt-1 ] ) ;
  993.     if ( read( Flkmem, (char*)&pte, sizeof( struct pte ) )
  994.     != sizeof( struct pte ) )
  995.     {
  996.         fprintf( stderr,
  997.               "sps - Can't read indir pte for upage of process %d\n",
  998.             p->pr_p.p_pid ) ;
  999.         return ( 0 ) ;
  1000.     }                               
  1001.     /* Now read the process' pte's from physical memory. We need to access
  1002.        sufficient pte's for the upage and for the command arguments. */
  1003.     memseek( Flmem, (long)ctob( pte.pg_pfnum+1 )
  1004.         - (UPAGES+CLSIZE)*sizeof( struct pte ) ) ;
  1005.     if ( read( Flmem, (char*)ptetbl, (UPAGES+CLSIZE)*sizeof( struct pte ) )
  1006.     != (UPAGES+CLSIZE)*sizeof( struct pte ) )
  1007.     {
  1008.         fprintf( stderr, "sps - Can't read page table of process %d\n",
  1009.             p->pr_p.p_pid ) ;
  1010.         return ( 0 ) ;
  1011.     }
  1012.     /* Now we can read the pages belonging to the upage.
  1013.        Here we read in an entire click at one go. */
  1014.     ncl = (sizeof( struct user ) + NBPG*CLSIZE - 1) / (NBPG*CLSIZE) ;
  1015.     while ( --ncl >= 0 )            
  1016.     {                               
  1017.         i = ncl * CLSIZE ;
  1018.         memseek( Flmem, (long)ctob( ptetbl[ CLSIZE+i ].pg_pfnum ) ) ;
  1019.         if ( read( Flmem, User.u_pg[i], CLSIZE*NBPG ) != CLSIZE*NBPG )
  1020.         {
  1021.             fprintf( stderr,
  1022.                 "sps - Can't read page 0x%x of process %d\n",
  1023.                 ptetbl[ CLSIZE+i ].pg_pfnum, p->pr_p.p_pid ) ;
  1024.             return ( 0 ) ;
  1025.         }
  1026.     }
  1027.     return ( 1 ) ;
  1028. }
  1029. SHAR_EOF
  1030. if test 2971 -ne "`wc -c < 'getupage.c'`"
  1031. then
  1032.     echo shar: error transmitting "'getupage.c'" '(should have been 2971 characters)'
  1033. fi
  1034. fi # end of overwriting check
  1035. echo shar: extracting "'globals1.c'" '(720 characters)'
  1036. if test -f 'globals1.c'
  1037. then
  1038.     echo shar: will not over-write existing file "'globals1.c'"
  1039. else
  1040. sed 's/^X//' << \SHAR_EOF > 'globals1.c'
  1041. # include       "sps.h"
  1042. # include       "flags.h"
  1043.  
  1044. /* Read/Write Variables global to the code of sps */
  1045.  
  1046. struct info                     Info ;          /* Information structure */
  1047.  
  1048. struct flags                    Flg ;           /* Flag options */
  1049.  
  1050. struct summary                  Summary ;       /* Summary of processes */
  1051.  
  1052. union  userstate                User ;          /* Upage of one process */
  1053.  
  1054. int                             Flmem, Flkmem, Flswap ; /* File descriptors */
  1055.  
  1056. unsigned                        Termwidth ;     /* Width of output device */
  1057.  
  1058. short                           Lastpgrp ;      /* Last process pgrp printed */
  1059.  
  1060. short                           Lastuid ;       /* Last process uid printed */
  1061. SHAR_EOF
  1062. if test 720 -ne "`wc -c < 'globals1.c'`"
  1063. then
  1064.     echo shar: error transmitting "'globals1.c'" '(should have been 720 characters)'
  1065. fi
  1066. fi # end of overwriting check
  1067. echo shar: extracting "'globals2.c'" '(5240 characters)'
  1068. if test -f 'globals2.c'
  1069. then
  1070.     echo shar: will not over-write existing file "'globals2.c'"
  1071. else
  1072. sed 's/^X//' << \SHAR_EOF > 'globals2.c'
  1073. # include       "sps.h"
  1074.  
  1075. /* Read Only variables, global to the code of sps ... */
  1076.  
  1077. /* Null ttyline device ... */
  1078. struct ttyline                  Notty = { 0, 0, "  ", 0 } ;
  1079.  
  1080. /*
  1081. ** The symbol table. For each address read from the kernel during
  1082. ** initialisation, this table shows the following:
  1083. **      i.   the name of that symbol within the kernel ;
  1084. **      ii.  whether an extra indirection is needed through the kernel,
  1085. **           i.e. whether the value of that symbol should be obtained
  1086. **           rather than its address.
  1087. **      iii. where the obtained value/address is placed in the Info structure ;
  1088. **      iv.  whether the obtained value is associated with a reason for
  1089. **           a process wait state.
  1090. */
  1091. /* The order of entries in this table is unimportant. */
  1092.  
  1093. extern struct info              Info ;
  1094.  
  1095. struct symbol   Symbollist[] =
  1096. {       
  1097.     /* Kernel addresses required in order to access process,
  1098.        tty and upage information. All these addresses should be
  1099.        located in the symbol file during initialisation. */
  1100.     { "_proc",      1,  (caddr_t*)&Info.i_proc0,    (char*)0        },
  1101.     { "_nproc",     1,  (caddr_t*)&Info.i_nproc,    (char*)0        },
  1102.     { "_text",      1,  (caddr_t*)&Info.i_text0,    (char*)0        },
  1103.     { "_ntext",     1,  (caddr_t*)&Info.i_ntext,    (char*)0        },
  1104.     { "_inode",     1,  (caddr_t*)&Info.i_inode0,   (char*)0        },
  1105.     { "_ninode",    1,  (caddr_t*)&Info.i_ninode,   (char*)0        },
  1106.     { "_swbuf",     1,  (caddr_t*)&Info.i_swbuf0,   (char*)0        },
  1107.     { "_nswbuf",    1,  (caddr_t*)&Info.i_nswbuf,   (char*)0        },
  1108.     { "_buf",       1,  (caddr_t*)&Info.i_buf0,     (char*)0        },
  1109.     { "_nbuf",      1,  (caddr_t*)&Info.i_nbuf,     (char*)0        },
  1110.     { "_ecmx",      1,  (caddr_t*)&Info.i_ecmx,     (char*)0        },
  1111.     { "_Usrptmap",  0,  (caddr_t*)&Info.i_usrptmap, (char*)0        },
  1112.     { "_usrpt",     0,  (caddr_t*)&Info.i_usrpt,    (char*)0        },
  1113.     { "_cdevsw",    0,  (caddr_t*)&Info.i_cdevsw,   (char*)0        },
  1114. # ifdef BSD42
  1115.     { "_quota",     1,  (caddr_t*)&Info.i_quota0,   (char*)0        },
  1116.     { "_nquota",    1,  (caddr_t*)&Info.i_nquota,   (char*)0        },
  1117.     { "_dmmin",     1,  (caddr_t*)&Info.i_dmmin,    (char*)0        },
  1118.     { "_dmmax",     1,  (caddr_t*)&Info.i_dmmax,    (char*)0        },
  1119.     { "_mbutl",     0,  (caddr_t*)&Info.i_mbutl,    (char*)0        },
  1120. # else
  1121.     { "_hz",        1,  (caddr_t*)&Info.i_hz,       (char*)0        },
  1122. # endif
  1123. # ifdef CHAOS
  1124.     { "_Chconntab", 0,  &Info.i_Chconntab,          (char*)0        },
  1125. # endif
  1126.     /* Kernel addresses associated with process wait states.
  1127.        It is not important if some of these addresses are unresolved
  1128.        at initialisation. */
  1129.     { "_fltab",     0,  &Info.i_waitstate[0],       "floppy"        },
  1130.     { "_tu",        0,  &Info.i_waitstate[1],       "tu58"          },
  1131.     { "_bfreelist", 0,  &Info.i_waitstate[2],       "buffer"        },
  1132.     { "_lp_softc",  0,  &Info.i_waitstate[3],       "printr"        },
  1133.     { "_lbolt",     0,  &Info.i_waitstate[4],       "lbolt"         },
  1134.     { "_runin",     0,  &Info.i_waitstate[5],       "runin"         },
  1135.     { "_runout",    0,  &Info.i_waitstate[6],       "runout"        },
  1136.     { "_ipc",       0,  &Info.i_waitstate[7],       "ptrace"        },
  1137.     { "_u",         0,  &Info.i_waitstate[8],       "pause"         },
  1138.     { "_freemem",   0,  &Info.i_waitstate[9],       "freemm"        },
  1139.     { "_kernelmap", 0,  &Info.i_waitstate[10],      "kermap"        },
  1140.     { "_cwaiting",  0,  &Info.i_waitstate[11],      "cwait"         },
  1141.     { "_rhpbuf",    0,  &Info.i_waitstate[12],      "rhpbuf"        },
  1142.     { "_rhtbuf",    0,  &Info.i_waitstate[13],      "rhtbuf"        },
  1143.     { "_ridcbuf",   0,  &Info.i_waitstate[14],      "ridcbf"        },
  1144.     { "_rikbuf",    0,  &Info.i_waitstate[15],      "rikbuf"        },
  1145.     { "_rmtbuf",    0,  &Info.i_waitstate[16],      "rmtbuf"        },
  1146.     { "_rrkbuf",    0,  &Info.i_waitstate[17],      "rrkbuf"        },
  1147.     { "_rrlbuf",    0,  &Info.i_waitstate[18],      "rrlbuf"        },
  1148.     { "_rrxbuf",    0,  &Info.i_waitstate[19],      "rrxbuf"        },
  1149.     { "_rswbuf",    0,  &Info.i_waitstate[20],      "rswbuf"        },
  1150.     { "_rtmbuf",    0,  &Info.i_waitstate[21],      "rtmbuf"        },
  1151.     { "_rtsbuf",    0,  &Info.i_waitstate[22],      "rtsbuf"        },
  1152.     { "_rudbuf",    0,  &Info.i_waitstate[23],      "rudbuf"        },
  1153.     { "_rupbuf",    0,  &Info.i_waitstate[24],      "rupbuf"        },
  1154.     { "_rutbuf",    0,  &Info.i_waitstate[25],      "rutbuf"        },
  1155.     { "_rvabuf",    0,  &Info.i_waitstate[26],      "rvabuf"        },
  1156.     { "_rvpbuf",    0,  &Info.i_waitstate[27],      "rvpbuf"        },
  1157.     { "_chtbuf",    0,  &Info.i_waitstate[28],      "chtbuf"        },
  1158.     { "_cmtbuf",    0,  &Info.i_waitstate[29],      "cmtbuf"        },
  1159.     { "_ctmbuf",    0,  &Info.i_waitstate[30],      "ctmbuf"        },
  1160.     { "_ctsbuf",    0,  &Info.i_waitstate[31],      "ctsbuf"        },
  1161.     { "_cutbuf",    0,  &Info.i_waitstate[32],      "cutbuf"        },
  1162. # ifdef BSD42
  1163.     { "_selwait",   0,  &Info.i_waitstate[33],      "select"        },
  1164. # endif
  1165. # ifdef CHAOS
  1166.     { "_Chrfclist", 0,  &Info.i_waitstate[34],      "chrfc"         },
  1167. # endif
  1168. # ifdef SUN
  1169.     { "_async_bufhead", 0,  &Info.i_waitstate[35],  "async"        },
  1170. # endif
  1171.     { (char*)0,     0,  (caddr_t*)0,                (char*)0        }
  1172. } ;
  1173. SHAR_EOF
  1174. if test 5240 -ne "`wc -c < 'globals2.c'`"
  1175. then
  1176.     echo shar: error transmitting "'globals2.c'" '(should have been 5240 characters)'
  1177. fi
  1178. fi # end of overwriting check
  1179. echo shar: extracting "'hashuid.c'" '(1421 characters)'
  1180. if test -f 'hashuid.c'
  1181. then
  1182.     echo shar: will not over-write existing file "'hashuid.c'"
  1183. else
  1184. sed 's/^X//' << \SHAR_EOF > 'hashuid.c'
  1185. # include       "sps.h"
  1186.  
  1187. /* The hashing functions themselves ... */
  1188. # define        HASHFN1( a )            (((a)*91 + 17) % MAXUSERID)
  1189. # define        HASHFN2( a )            (((a) + 47) % MAXUSERID)
  1190.  
  1191. /*
  1192. ** HASHUID - Returns a pointer to a slot in the hash table that corresponds
  1193. ** to the hash table entry for `uid'. It returns a null pointer if there is
  1194. ** no such slot.
  1195. */
  1196. struct hashtab  *hashuid ( uid )
  1197.  
  1198. int                             uid ;
  1199.  
  1200. {
  1201.     register struct hashtab *hp ;
  1202.     register int            i ;
  1203.     register int            j ;
  1204.     extern struct info      Info ;
  1205.  
  1206.     j = HASHFN1( uid ) ;
  1207.     for ( i = 0 ; i < MAXUSERID ; i++ )
  1208.     {
  1209.         hp = &Info.i_hnames[ j ] ;
  1210.         if ( !hp->h_uname[0] )
  1211.             return ( (struct hashtab*)0 ) ;
  1212.         if ( hp->h_uid == uid )
  1213.             return ( hp ) ;
  1214.         j = HASHFN2( j ) ;
  1215.     }
  1216.     return ( (struct hashtab*)0 ) ;
  1217. }
  1218.  
  1219. /*
  1220. ** HASHNEXT - Returns a pointer to the next slot in the hash table that
  1221. ** may be use for storing information for `uid'. It returns a null pointer
  1222. ** if there are no more free slots available.
  1223. */
  1224. struct hashtab  *hashnext ( uid )
  1225.  
  1226. int                             uid ;
  1227.  
  1228. {
  1229.     register struct hashtab *hp ;
  1230.     register int            i ;
  1231.     register int            j ;
  1232.     extern struct info      Info ;
  1233.  
  1234.     j = HASHFN1( uid ) ;
  1235.     for ( i = 0 ; i < MAXUSERID ; i++ )
  1236.     {
  1237.         hp = &Info.i_hnames[ j ] ;
  1238.         if ( !hp->h_uname[0] )
  1239.             return ( hp ) ;
  1240.         j = HASHFN2( j ) ;
  1241.     }
  1242.     return ( (struct hashtab*)0 ) ;
  1243. }
  1244. SHAR_EOF
  1245. if test 1421 -ne "`wc -c < 'hashuid.c'`"
  1246. then
  1247.     echo shar: error transmitting "'hashuid.c'" '(should have been 1421 characters)'
  1248. fi
  1249. fi # end of overwriting check
  1250. echo shar: extracting "'initialise.c'" '(1905 characters)'
  1251. if test -f 'initialise.c'
  1252. then
  1253.     echo shar: will not over-write existing file "'initialise.c'"
  1254. else
  1255. sed 's/^X//' << \SHAR_EOF > 'initialise.c'
  1256. # include       "sps.h"
  1257. # include       "flags.h"
  1258. # include       <pwd.h>
  1259. # include       <stdio.h>
  1260.  
  1261. /*
  1262. ** INITIALISE - Called to reset the `Info' structure with new kernel
  1263. ** addresses and user and tty information.
  1264. */
  1265. initialise ()
  1266. {
  1267.     register FILE           *fd ;
  1268.     char                    *fileinfo ;
  1269.     extern struct flags     Flg ;
  1270.     extern struct info      Info ;
  1271.     FILE                    *fopen() ;
  1272.  
  1273.     fileinfo = Flg.flg_j ? Flg.flg_j : FILE_INFO ;
  1274.     /* Read kernel addresses */
  1275.     initsymbols() ;                 
  1276.     /* Read user names */
  1277.     initusers() ;                   
  1278.     (void)umask( ~0644 ) ;          
  1279.     if ( !(fd = fopen( fileinfo, "w" )) )
  1280.     {
  1281.         fprintf( stderr, "sps - Can't create info file %s", fileinfo ) ;
  1282.         sysperror() ;
  1283.     }
  1284.     /* Find tty addresses */
  1285.     inittty() ;                     
  1286.     if ( fwrite( (char*)&Info, sizeof( struct info ), 1, fd ) != 1 )
  1287.     {
  1288.         fprintf( stderr, "sps - Can't write info file %s", fileinfo ) ;
  1289.         sysperror() ;
  1290.         exit( 1 ) ;
  1291.     }
  1292.     (void)fclose( fd ) ;
  1293.     printf( "sps is initialised\n" ) ;
  1294. }
  1295.  
  1296. /* INITUSERS - Read the passwd file and fill in the user name arrays */
  1297. initusers ()
  1298. {
  1299.     register struct passwd  *pw ;
  1300.     register struct hashtab *hp ;
  1301.     struct passwd           *getpwent() ;
  1302.     char                    *strncpy() ;
  1303.     struct hashtab          *hashuid(), *hashnext() ;
  1304.  
  1305.     while ( pw = getpwent() )
  1306.     {       /* For each user in the passwd file, first see if that uid
  1307.            has been already allocated in the hash table. */
  1308.         if ( hp = hashuid( pw->pw_uid ) )
  1309.         {
  1310.             fprintf( stderr,
  1311.            "sps - Names %s and %s conflict in passwd file for uid %d\n",
  1312.                 hp->h_uname, pw->pw_name, pw->pw_uid ) ;
  1313.             continue ;
  1314.         }
  1315.         /* Try to find a free slot in the hash table and fill it. */
  1316.         if ( !(hp = hashnext( pw->pw_uid )) )
  1317.             prexit( "sps - Too many users in passwd file\n" ) ;
  1318.         hp->h_uid = pw->pw_uid ;
  1319.         (void)strncpy( hp->h_uname, pw->pw_name, UNAMELEN ) ;
  1320.     }
  1321.     (void)endpwent() ;
  1322. }
  1323. SHAR_EOF
  1324. if test 1905 -ne "`wc -c < 'initialise.c'`"
  1325. then
  1326.     echo shar: error transmitting "'initialise.c'" '(should have been 1905 characters)'
  1327. fi
  1328. fi # end of overwriting check
  1329. echo shar: extracting "'initsymbols.c'" '(2994 characters)'
  1330. if test -f 'initsymbols.c'
  1331. then
  1332.     echo shar: will not over-write existing file "'initsymbols.c'"
  1333. else
  1334. sed 's/^X//' << \SHAR_EOF > 'initsymbols.c'
  1335. # include       "sps.h"
  1336. # include       "flags.h"
  1337. # ifdef BSD42
  1338. # include       <sys/file.h>
  1339. # endif
  1340. # include       <nlist.h>
  1341. # include       <stdio.h>
  1342.  
  1343. /* INITSYMBOLS - Reads kmem values into the Info structure */
  1344. /*
  1345. ** THIS CODE COPIES KMEM VALUES INTO THE INFO STRUCTURE ASSUMING THAT
  1346. ** VALUES READ FROM THE KERNEL HAVE TYPE CADDR_T. THEREFORE, WE ARE
  1347. ** MAKING THE DUBIOUS ASSUMPTION THAT INTS, POINTERS AND CADDR_T's
  1348. ** HAVE IDENTICAL SIZES.
  1349. */
  1350. initsymbols ()
  1351. {
  1352.     register struct nlist   *np ;
  1353.     register struct symbol  *s ;
  1354.     register struct nlist   *np0 ;
  1355.     char                    *filesymbol ;
  1356.     extern int              Flkmem ;
  1357.     extern struct flags     Flg ;
  1358.     extern struct symbol    Symbollist[] ;
  1359.     extern struct info      Info ;
  1360.     char                    *getcore() ;
  1361.     char                    *strncpy() ;
  1362.  
  1363.     filesymbol = Flg.flg_s ? Flg.flg_s : FILE_SYMBOL ;
  1364.     /* Find the length of the symbol table */
  1365.     for ( s = Symbollist ; s->s_kname ; s++ )
  1366.         ;
  1367.     /* Construct an nlist structure by copying names from the symbol table*/
  1368.     np0 = (struct nlist*)getcore( (s-Symbollist+1)*sizeof( struct nlist ) );
  1369.     for ( s = Symbollist, np = np0 ; s->s_kname ; s++, np++ )
  1370.     {                                       
  1371.         np->n_name = s->s_kname ;       
  1372.         np[1].n_name = (char*)0 ;       
  1373.         np->n_value = 0 ;
  1374.     }
  1375. # ifdef BSD42
  1376.     if ( access( filesymbol, R_OK ) < 0 )
  1377. # else
  1378.     if ( access( filesymbol, 4 ) < 0 )
  1379. # endif
  1380.     {
  1381.         fprintf( stderr, "sps - Can't open symbol file %s", filesymbol);
  1382.         sysperror() ;
  1383.     }
  1384.     /* Get kernel addresses */
  1385.     nlist( filesymbol, np0 ) ;              
  1386.     if ( np0[0].n_value == -1 )
  1387.     {
  1388.         fprintf( stderr, "sps - Can't read symbol file %s", filesymbol);
  1389.         sysperror() ;
  1390.     }
  1391.     for ( s = Symbollist, np = np0 ; s->s_kname ; s++, np++ )
  1392.     {                                       
  1393.         if ( !np->n_value )             
  1394.         {
  1395.             fprintf( stderr, "sps - Can't find symbol %s in %s",
  1396.                 np->n_name, filesymbol ) ;
  1397.             /* Assume this error to be unimportant if the address
  1398.                is only associated with a process wait state.
  1399.                This may happen if the system has been configured
  1400.                without a particular device. */
  1401.             fprintf( stderr, &Info.i_waitstate[ 0 ] <= s->s_info
  1402.                 && s->s_info < &Info.i_waitstate[ NWAITSTATE ]
  1403.                 ? " (error is not serious)\n"
  1404.                 : " (ERROR MAY BE SERIOUS)\n" ) ;
  1405.             *s->s_info = (caddr_t)0 ;
  1406.             continue ;
  1407.         }
  1408.         /* If no indirection is required, just copy the obtained value
  1409.            into the `Info' structure. */
  1410.         if ( !s->s_indirect )           
  1411.         {                               
  1412.         /* DUBIOUS ASSUMPTION THAT KMEM VALUE HAS SIZE OF A CADDR_T */
  1413.             *s->s_info = (caddr_t)np->n_value ;
  1414.             continue ;              
  1415.         }                               
  1416.         /* Otherwise one level of indirection is required. Using the
  1417.            obtained address, look again in the kernel for the value */
  1418.         memseek( Flkmem, (long)np->n_value ) ;
  1419.         /* DUBIOUS ASSUMPTION THAT KMEM VALUE HAS SIZE OF A CADDR_T */
  1420.         (void)read( Flkmem, (char*)s->s_info, sizeof(caddr_t) ) ;
  1421.     }
  1422.     free( (char*)np0 ) ;
  1423. }
  1424. SHAR_EOF
  1425. if test 2994 -ne "`wc -c < 'initsymbols.c'`"
  1426. then
  1427.     echo shar: error transmitting "'initsymbols.c'" '(should have been 2994 characters)'
  1428. fi
  1429. fi # end of overwriting check
  1430. echo shar: extracting "'inittty.c'" '(3544 characters)'
  1431. if test -f 'inittty.c'
  1432. then
  1433.     echo shar: will not over-write existing file "'inittty.c'"
  1434. else
  1435. sed 's/^X//' << \SHAR_EOF > 'inittty.c'
  1436. # include       "sps.h"
  1437. # include       <h/conf.h>
  1438. # include       <h/tty.h>
  1439. # include       <sys/stat.h>
  1440. # include       <stdio.h>
  1441.  
  1442. /* INITTTY - Initialise the tty part of the info structure */
  1443. inittty ()
  1444. {
  1445.     register struct ttyline *lp ;
  1446. # ifdef BSD42
  1447.     register struct direct  *dp ;
  1448.     DIR                     *dfd ;
  1449. # else
  1450.     struct direct           dir ;
  1451.     FILE                    *dfd ;
  1452. # endif
  1453.     struct stat             statbuf ;
  1454.     static char             filedev[] = FILE_DEV ;
  1455.     extern struct info      Info ;
  1456.     extern int              Flkmem ;
  1457. # ifdef BSD42
  1458.     DIR                     *opendir() ;
  1459.     struct direct           *readdir() ;
  1460. # else
  1461.     FILE                    *fopen() ;
  1462. # endif
  1463.  
  1464.     lp = Info.i_ttyline ;
  1465. # ifdef BSD42
  1466.     if ( !(dfd = opendir( filedev )) )
  1467. # else
  1468.     if ( !(dfd = fopen( filedev, "r" )) )
  1469. # endif
  1470.         prexit( "Can't open %s\n", filedev ) ;
  1471.     if ( chdir( filedev ) < 0 )
  1472.         prexit( "sps - Can't chdir to %s\n", filedev ) ;
  1473. # ifdef BSD42
  1474.     /* Read all entries in the device directory, looking for ttys */
  1475.     while ( dp = readdir( dfd ) )
  1476.     {       /* Skip entries that do not match "tty" or "console" */
  1477.         if ( strncmp( "tty", dp->d_name, 3 )
  1478.         &&   strcmp( "console", dp->d_name ) )
  1479.             continue ;
  1480.         /* Skip "tty" itself */
  1481.         if ( dp->d_namlen == 3 )
  1482.             continue ;
  1483. # ifdef CHAOS
  1484.         /* Skip chaos ttys ; they are accessed during ttystatus() */
  1485.         if ( dp->d_namelen > 3 &&
  1486.         dp->d_name[ sizeof( "tty" ) - 1 ] == 'C' )
  1487.             continue ;
  1488. # endif
  1489.         if ( lp >= &Info.i_ttyline[ MAXTTYS ] )
  1490.             prexit( "sps - Too many ttys in %s\n", filedev ) ;
  1491.         /* Copy the tty name into the information entry */
  1492.         if ( !strcmp( dp->d_name, "console" ) )
  1493.         {
  1494.             lp->l_name[0] = 'c' ;
  1495.             lp->l_name[1] = 'o' ;
  1496.         }
  1497.         else
  1498.         {
  1499.             lp->l_name[0] = dp->d_name[3] ;
  1500.             lp->l_name[1] = dp->d_name[4] ;
  1501.         }
  1502.         /* Ensure that this tty is actually a valid character device */
  1503.         if ( stat( dp->d_name, &statbuf ) < 0 )
  1504.             continue ;
  1505. # else
  1506.     /* Read all entries in the device directory, looking for ttys */
  1507.     while ( fread( (char*)&dir, sizeof( struct direct ), 1, dfd ) == 1 )
  1508.     {       /* Skip entries that do not match "tty" or "console" */
  1509.         if ( strncmp( "tty", dir.d_name, 3 )
  1510.         &&   strcmp( "console", dir.d_name ) )
  1511.             continue ;
  1512.         /* Skip "tty" itself */
  1513.         if ( dir.d_name[3] == '\0' )
  1514.             continue ;
  1515. # ifdef CHAOS
  1516.         /* Skip chaos ttys ; they are accessed during ttystatus() */
  1517.         if ( dir.d_name[ sizeof( "tty" ) - 1 ] == 'C' )
  1518.             continue ;
  1519. # endif
  1520.         if ( lp >= &Info.i_ttyline[ MAXTTYS ] )
  1521.             prexit( "sps - Too many ttys in %s\n", filedev ) ;
  1522.         /* Copy the tty name into the information entry */
  1523.         if ( !strcmp( dir.d_name, "console" ) )
  1524.         {
  1525.             lp->l_name[0] = 'c' ;
  1526.             lp->l_name[1] = 'o' ;
  1527.         }
  1528.         else
  1529.         {
  1530.             lp->l_name[0] = dir.d_name[3] ;
  1531.             lp->l_name[1] = dir.d_name[4] ;
  1532.         }
  1533.         /* Ensure that this tty is actually a valid character device */
  1534.         if ( stat( dir.d_name, &statbuf ) < 0 )
  1535.             continue ;
  1536. # endif
  1537.         if ( (statbuf.st_mode & S_IFMT) != S_IFCHR )
  1538.             continue ;
  1539.         /* Find the device # of the tty and the address of its
  1540.            associated struct tty in /dev/kmem. */
  1541.         lp->l_dev = statbuf.st_rdev ;
  1542.         memseek( Flkmem,
  1543.              (long)&Info.i_cdevsw[ major( statbuf.st_rdev ) ].d_ttys ) ;
  1544.         if ( read( Flkmem, (char*)&lp->l_addr, sizeof( lp->l_addr ) )
  1545.         != sizeof( lp->l_addr ) )
  1546.         {
  1547.             fprintf( stderr, "sps - Can't read struct tty for %s\n",
  1548. # ifdef BSD42
  1549.                 dp->d_name ) ;
  1550. # else
  1551.                 dir.d_name ) ;
  1552. # endif
  1553.             continue ;
  1554.         }
  1555.         lp->l_addr += (int)minor( statbuf.st_rdev ) ;
  1556.         lp++ ;
  1557.     }
  1558. # ifdef BSD42
  1559.     (void)closedir( dfd ) ;
  1560. # else
  1561.     (void)fclose( dfd ) ;
  1562. # endif
  1563. }
  1564. SHAR_EOF
  1565. if test 3544 -ne "`wc -c < 'inittty.c'`"
  1566. then
  1567.     echo shar: error transmitting "'inittty.c'" '(should have been 3544 characters)'
  1568. fi
  1569. fi # end of overwriting check
  1570. #    End of shell archive
  1571. exit 0
  1572.